﻿#include "systeminfoutils.h"

#include <QDebug>
#include <QDir>
#include <QFile>
#include <QList>
#include <QProcess>
#include <QStorageInfo>
#include <QTextStream>

QMap<QString, QString> SystemInfoUtils::getCPUInfo() {
    QMap<QString, QString> cpuInfoMap;

    QString originalLcAllValue;
    // 保存 LC_ALL 环境变量的原始值
    originalLcAllValue = qgetenv("LC_ALL");

    // 设置 LC_ALL 环境变量为英文
    qputenv("LC_ALL", "C");

    {
        // 执行 lscpu 命令
        QProcess lscpu;
        lscpu.start("lscpu");
        lscpu.waitForFinished(-1);

        // 读取输出
        QString lscpuOutput = QString::fromLocal8Bit(lscpu.readAllStandardOutput());

        // 解析输出并存储到 QMap 中
        QStringList lines = lscpuOutput.split("\n");
        foreach (QString line, lines) {
            line = line.trimmed();
            if (line.contains(":")) {
                QStringList parts = line.split(":");
                QString key = parts[0].trimmed();
                QString value = parts[1].trimmed();
                cpuInfoMap.insert(key, value);
            }
        }
    }
    qputenv("LC_ALL", originalLcAllValue.toUtf8());

    return cpuInfoMap;
}

QList<double> SystemInfoUtils::getCPUCoresTemperatures() {
    QList<double> temperatures;

    // 打开/sys/class/hwmon/目录
    QDir hwmonDir("/sys/class/hwmon/");
    if (!hwmonDir.exists()) {
        qDebug() << "Error: /sys/class/hwmon/ directory does not exist.";
        return temperatures;
    }

    // 获取目录下的所有文件夹（每个文件夹对应一个硬件监控设备）
    QStringList hwmonDirs = hwmonDir.entryList(QDir::Dirs | QDir::NoDotAndDotDot);

    // 遍历所有硬件监控设备
    foreach (QString hwmonDirName, hwmonDirs) {
        QString hwmonPath = hwmonDir.absoluteFilePath(hwmonDirName);

        // 检查是否是CPU温度监控设备
        QFile nameFile(hwmonPath + "/name");
        if (!nameFile.open(QIODevice::ReadOnly | QIODevice::Text)) {
            qDebug() << "Error: Unable to open" << hwmonPath + "/name";
            continue;
        }

        QTextStream nameStream(&nameFile);
        QString name = nameStream.readAll().trimmed();
        nameFile.close();

        // 如果是CPU温度监控设备（例如，名字为"coretemp"）
        if (name == "coretemp") {
            // 遍历该设备下的所有温度文件
            QDir tempDir(hwmonPath);
            QStringList tempFiles = tempDir.entryList(QDir::Files);

            foreach (QString tempFile, tempFiles) {
                // 检查是否是温度标签文件
                if (tempFile.startsWith("temp") && tempFile.endsWith("_label")) {
                    QString labelFilePath = hwmonPath + "/" + tempFile;
                    QFile labelFile(labelFilePath);
                    if (!labelFile.open(QIODevice::ReadOnly | QIODevice::Text)) {
                        qDebug() << "Error: Unable to open" << labelFilePath;
                        continue;
                    }

                    QTextStream labelStream(&labelFile);
                    QString label = labelStream.readAll().trimmed();
                    labelFile.close();

                    // 如果标签以"Core"开头，则读取对应的温度值
                    if (label.startsWith("Core")) {
                        QString tempInputFileName = tempFile.replace("_label", "_input");
                        QString tempInputFilePath = hwmonPath + "/" + tempInputFileName;

                        QFile tempInputFile(tempInputFilePath);
                        if (!tempInputFile.open(QIODevice::ReadOnly | QIODevice::Text)) {
                            qDebug() << "Error: Unable to open" << tempInputFilePath;
                            continue;
                        }

                        QTextStream tempStream(&tempInputFile);
                        QString tempStr = tempStream.readAll().trimmed();
                        tempInputFile.close();

                        bool ok;
                        int temperature = tempStr.toInt(&ok);
                        if (!ok) {
                            qDebug() << "Error: Invalid temperature value in" << tempInputFilePath;
                            continue;
                        }

                        // 将温度值转换为摄氏度并添加到列表中
                        temperatures.append(temperature / 1000.0); // 转换为摄氏度
                    }
                }
            }
        }
    }

    return temperatures;
}

QMap<QString, QString> SystemInfoUtils::getSystemInfo() {
    QMap<QString, QString> systemInfoMap;

    // 获取系统主机名
    QString hostName = QSysInfo::machineHostName();
    systemInfoMap[SYS_INFO_HOSTNAME] = hostName;

    QString systemName = QSysInfo::prettyProductName();
    systemInfoMap[SYS_INFO_SYSTEMNAME] = systemName;

    // 获取内核版本
    QString kernelVersion = QSysInfo::kernelVersion();
    systemInfoMap[SYS_INFO_KERNELVERSIONE] = kernelVersion;

    return systemInfoMap;
}

double SystemInfoUtils::getCPULoad() {
    static cppc::CpuOccupy m_lastCpu = {"", 0, 0, 0, 0};
    if (m_lastCpu.name.empty()) {
        m_lastCpu = cppc::SystemUtil::getCpuOccupy();
        return -1;
    } else {
        cppc::CpuOccupy t_nowCpu = cppc::SystemUtil::getCpuOccupy();
        cppc::CpuInfo cpuInfo = cppc::SystemUtil::calCpuInfo(m_lastCpu, t_nowCpu);
        m_lastCpu = t_nowCpu;
        return cpuInfo.usage;
    }
}

double SystemInfoUtils::getRamLoad() {
    cppc::RamInfo ramInfo = cppc::SystemUtil::getRamInfo();
    return ramInfo.usage;
}

QList<QStorageInfo> SystemInfoUtils::getStorageInfo() {
    QList<QStorageInfo> storageList;

    // 遍历每个磁盘分区信息
    for (const QStorageInfo &storage : QStorageInfo::mountedVolumes()) {
        if (storage.isValid() && storage.isReady()) {
            if (storage.rootPath().startsWith("/snap") || storage.device() == "tmpfs") {
                continue;
            }
            storageList.append(storage);
            //            qDebug() << "Device: " << storage.device();
            //            qDebug() << "File system type: " << storage.fileSystemType();
            //            qDebug() << "Root path: " << storage.rootPath();
            //            qDebug() << "Size: " << storage.bytesTotal() / (1024 * 1024) << "MB";
            //            qDebug() << "Free: " << storage.bytesAvailable() / (1024 * 1024) << "MB";
        }
    }

    return storageList;
}
